package mrpanyu.guitool.yunduan;

import java.io.File;
import java.io.FileInputStream;
import java.util.Base64;
import java.util.concurrent.atomic.AtomicBoolean;

import mrpanyu.guitool.base.annotation.Action;
import mrpanyu.guitool.base.annotation.Parameter;
import mrpanyu.guitool.base.annotation.ToolModel;
import mrpanyu.guitool.base.model.ParameterType;
import mrpanyu.guitool.base.model.Tool;
import mrpanyu.guitool.base.util.CommonUtils;

@ToolModel(displayName = "云端导入-Host端", description = "使用云端VM内可以读取Host机剪贴板文本的功能，传输文件。这个在Host机运行，用于发送文件")
public class YunduanImportHost {

	@Parameter(displayName = "导入文件", type = ParameterType.FILE, order = 1)
	private File inputFile;

	@Parameter(displayName = "分片大小", description = "每次传输的字节数，设置越大传输越快，但失败率越高", type = ParameterType.SELECT, options = {
			"512", "1024", "2048", "4096", "6144", "8192" }, order = 2)
	private String pieceSizeStr = "8192";

	@Parameter(displayName = "分片传输间隔毫秒", description = "每次传输间隔毫秒数，设置越小传输越快，但失败率越高", order = 3)
	private String pieceDelayStr = "400";

	@Parameter(displayName = "跳过分片数", description = "用于续传文件，跳过已传输的前n个分片数据", order = 3)
	private String skipPiecesStr = "0";

	private AtomicBoolean stopFlag = new AtomicBoolean(false);

	@Action(displayName = "准备传输", order = 1)
	public void ready(Tool tool) throws Exception {
		tool.clearMessages();
		if (inputFile == null) {
			tool.errorMessage("请选择导入文件");
			return;
		}
		long skipPieces = Long.parseLong(skipPiecesStr);
		setClipboardText("<ready-" + skipPieces + ">");
		if (skipPieces == 0) {
			tool.infoMessage("准备完毕，从头开始传输文件，请启动VM端读取监听");
		} else {
			tool.infoMessage("准备完毕，从分片" + (skipPieces + 1) + "开始续传文件，请启动VM端读取监听");
		}
	}

	@Action(displayName = "开始传输", order = 2)
	public void run(Tool tool) throws Exception {
		tool.clearMessages();
		int pieceSize = Integer.parseInt(pieceSizeStr);
		long pieceDelay = Long.parseLong(pieceDelayStr);
		long skipPieces = Long.parseLong(skipPiecesStr);
		stopFlag.set(false);
		ready(tool);
		try (FileInputStream fin = new FileInputStream(inputFile)) {
			long pieceNo = 1;
			if (skipPieces > 0) {
				fin.skip((long) pieceSize * skipPieces);
				pieceNo = skipPieces + 1;
			}
			byte[] buf = new byte[pieceSize];
			int len = fin.read(buf);
			while (len > 0) {
				if (stopFlag.get()) {
					break;
				}
				byte[] d = new byte[len];
				System.arraycopy(buf, 0, d, 0, len);
				String b64 = Base64.getEncoder().encodeToString(d);
				setClipboardText("<p-" + pieceNo + ">" + b64);
				tool.infoMessage("当前分片: " + pieceNo + ", 总共已传输: " + (pieceNo * pieceSize / 1024) + "KB");
				Thread.sleep(pieceDelay);
				len = fin.read(buf);
				pieceNo++;
			}
		}
		if (stopFlag.get()) {
			setClipboardText("<stopped>");
			tool.errorMessage("已停止传输");
		} else {
			setClipboardText("<done>");
			tool.infoMessage("已完成传输");
		}
	}

	@Action(displayName = "停止传输", order = 3)
	public void stop(Tool tool) throws Exception {
		stopFlag.set(true);
	}

	public void setClipboardText(String text) {
		RuntimeException ex = null;
		for (int i = 0; i < 3; i++) {
			try {
				CommonUtils.setClipboardText(text);
				return;
			} catch (RuntimeException e) {
				ex = e;
			}
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// ignore
			}
		}
		throw ex;
	}

}
